import { Camera, RenderTexture, UITransform, view, Node, math, gfx, director, ImageAsset, Texture2D, SpriteFrame, Sprite, sys, tween, Vec3, v3, profiler, instantiate, native } from "cc";
import { Logger } from "./Logger";
import { Canvas2Image } from "./Canvas2Image";
import { AppConfig } from "../config/AppConfig";
import { NativeSdkHelper } from "../sdk/NativeSdkHelper";

export class ScreenShotHelper {

    private static _instance: ScreenShotHelper;
    public static get instance(): ScreenShotHelper {
        if (!ScreenShotHelper._instance) {
            ScreenShotHelper._instance = new ScreenShotHelper();
        }
        return ScreenShotHelper._instance;
    }

    private captureCamera: Camera = null;

    private renderTex: RenderTexture = null;

    private _buffer: Uint8Array = null; //截图图片数据

    //web html
    private _canvas: HTMLCanvasElement = null;
    private canvas2Image: Canvas2Image = null;

    private defaultOrthoHeight: number = 362    //摄像机

    private showNode: Node

    public init(camera: Camera) {
        this.captureCamera = camera
        this.captureCamera.enabled = false
        this.defaultOrthoHeight = this.captureCamera.orthoHeight
        this.canvas2Image = Canvas2Image.getInstance();
    }

    /**
     * 设置 节点 layer
     * @param layer 
     * @param targetNode 
     */
    private setNodeLayer(layer: number, targetNode: Node) {
        targetNode.layer = layer
        // Logger.log("setNodeLayer===", layer, targetNode)
        for (let i = 0; i < targetNode.children.length; i++) {
            this.setNodeLayer(layer, targetNode.children[i])
        }
    }

    //截图某个节点
    public captureNode(targetNode: Node, showNode: Node = null) {
        this.showNode = showNode
        this.renderTex = new RenderTexture();
        let width: number = targetNode.getComponent(UITransform).width;
        let height: number = targetNode.getComponent(UITransform).height;
        this.renderTex.reset({
            width: width,
            height: height
        })
        this.captureCamera.targetTexture = this.renderTex
        if (width > height) {
            let rate: number = width / AppConfig.instance.DesignResolution.W;
            this.captureCamera.orthoHeight = rate * this.defaultOrthoHeight
            // Logger.log("width>height", AppConfig.instance.DesignResolution.W, width, this.captureCamera.orthoHeight, this.captureCamera.rect.width)
        } else {
            let rate: number = height / AppConfig.instance.DesignResolution.H
            this.captureCamera.orthoHeight = rate * this.defaultOrthoHeight
            // Logger.log("width>height", AppConfig.instance.DesignResolution.H, height, this.captureCamera.orthoHeight)
        }

        let copyTargetNode: Node = instantiate(targetNode)
        copyTargetNode.getComponent(UITransform).anchorX = 0.5
        copyTargetNode.getComponent(UITransform).anchorY = 0.5
        copyTargetNode.setPosition(0, 0)
        copyTargetNode.parent = this.captureCamera.node
        copyTargetNode.active = true
        this.setNodeLayer(this.captureCamera.node.layer, copyTargetNode)
        Logger.log("captureCamera=layer=", this.captureCamera.node.layer)
        this.captureCamera.node.active = true
        this.captureCamera.enabled = true
        this.captureCamera.scheduleOnce(() => {
            let targetPos: math.Vec3 = copyTargetNode.getPosition()
            let texBuffers: Uint8Array[] = [];
            texBuffers[0] = new Uint8Array(width * height * 4);
            let region: gfx.BufferTextureCopy = new gfx.BufferTextureCopy();
            Logger.log("worldPos==", width, height, targetPos.x, targetPos.y)
            region.texOffset.x = targetPos.x;
            region.texOffset.y = targetPos.y;
            region.texExtent.width = width;
            region.texExtent.height = height;
            director.root.device.copyTextureToBuffers(this.renderTex.getGFXTexture(), texBuffers, [region]);
            this._buffer = texBuffers[0];
            this.saveAsImage(width, height, this._buffer);
            copyTargetNode.destroy()
            this.captureCamera.enabled = false
            if (showNode) {
                // this.showImage(width, height, showNode);
            }
        }, 0)
    }

    //展示截图
    private showImage(width: number, height: number, showNode: Node) {
        let img: ImageAsset = new ImageAsset();
        img.reset({
            _data: this._buffer,
            width: width,
            height: height,
            format: Texture2D.PixelFormat.RGBA8888,
            _compressed: false
        });
        let texture = new Texture2D();
        texture.image = img;
        let sf: SpriteFrame = new SpriteFrame();
        sf.texture = texture;
        sf.packable = false;
        showNode.addComponent(Sprite).spriteFrame = sf;
        showNode.getComponent(Sprite).spriteFrame.flipUVY = true;
        showNode.getComponent(UITransform).setContentSize(width, height);
        this.doCaptureAnim();
    }

    // 做截图动画
    private doCaptureAnim() {
        if (this.showNode) {
            let scale_fator = 0.95;
            let arrived_fator = 0.3;
            let pos: math.Vec3 = v3(view.getVisibleSize().width / 2 - 100, view.getVisibleSize().height / 2 - 100)
            tween(this.showNode)
                .to(0.2, { scale: new Vec3(scale_fator, scale_fator, 1) })
                .to(0.3, { scale: new Vec3(1, 1, 1) })
                .parallel(
                    tween(this.showNode).to(0.5, { scale: new Vec3(arrived_fator, arrived_fator, 1) }),
                    tween(this.showNode).to(0.5, { position: pos })
                ).start();
        }
    }
    //保存截图 
    private saveAsImage(width: number, height: number, arrayBuffer: Uint8Array) {
        width = Math.round(width);
        height = Math.round(height);
        Logger.log("saveAsImage===", width, height)
        if (sys.isBrowser) {
            if (!this._canvas) {
                this._canvas = document.createElement('canvas');
                this._canvas.width = width;
                this._canvas.height = height;
            }
            let ctx = this._canvas.getContext('2d')!;
            let rowBytes = width * 4;
            for (let row = 0; row < height; row++) {
                let sRow = height - 1 - row;

                let imageData = ctx.createImageData(width, 1);
                let start = sRow * width * 4;

                for (let i = 0; i < rowBytes; i++) {
                    imageData.data[i] = arrayBuffer[start + i];
                }
                ctx.putImageData(imageData, 0, row);
            }
            // @ts-ignore
            this.canvas2Image.saveAsPNG(this._canvas, width, height);
        }
        else if (sys.isNative) {
            let picFolder: string = native.fileUtils.getWritablePath() + "pic";
            if (!native.fileUtils.isDirectoryExist(picFolder)) {
                native.fileUtils.createDirectory(picFolder)
            }
            let filePath: string = picFolder + "/capture.png"
            native.saveImageData(arrayBuffer, width, height, filePath)
            setTimeout(() => {
                NativeSdkHelper.save2PhotoAlbum(filePath)
            }, 1000);

        } else if (sys.platform == sys.Platform.WECHAT_GAME) {
            if (!this._canvas) {
                // @ts-ignore
                this._canvas = wx.createCanvas();
                this._canvas.width = width;
                this._canvas.height = height;
            } else {
                this.clearCanvas();
            }
            var ctx = this._canvas.getContext('2d');
            var rowBytes = width * 4;
            for (let row = 0; row < height; row++) {
                let sRow = height - 1 - row;
                let imageData = ctx.createImageData(width, 1);
                let start = sRow * width * 4;
                for (let i = 0; i < rowBytes; i++) {
                    imageData.data[i] = arrayBuffer[start + i];
                }
                ctx.putImageData(imageData, 0, row);
            }
            // @ts-ignore
            this._canvas.toTempFilePath({
                x: 0,
                y: 0,
                width: this._canvas.width,
                height: this._canvas.height,
                destWidth: this._canvas.width,
                destHeight: this._canvas.height,
                fileType: "png",
                success: function (res) {
                    // @ts-ignore
                    wx.showToast({ title: "截图成功" });
                    // @ts-ignore
                    wx.saveImageToPhotosAlbum({
                        filePath: res.tempFilePath,
                        success: function (res) {
                            // @ts-ignore
                            wx.showToast({ title: "成功保存到设备相册" })
                        }
                    });
                }
            })
        }
    }


    private clearCanvas() {
        let ctx = this._canvas.getContext('2d');
        ctx.clearRect(0, 0, this._canvas.width, this._canvas.height);
    }



}